package com.huanling.main.keyconflictdealer;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.json.JSONUtil;
import com.huanling.main.exception.ConflictKeyException;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;

/**
 * 如果设置了参照列，则根据参照列判断，相等的两条数据判断为重复数据，仅有重复数据不中断，输出重复数据到日志
 * 若没有设置参照列，则都认为是"相同元素"即重复数据
 *
 * @author guibo.sun
 * @since 16 七月 2021
 */
public class DuplicateIgnoreErrorOutPutDealer extends AbstractConflictKeyDealer implements LogNeeded {

    private ConflictKeyContext conflictKeyContext;

    @Override
    void preDeal(ConflictKeyContext conflictKeyContext, String key, Map<String, Object> oldValue, Map<String, Object> newValue) {
        this.conflictKeyContext = conflictKeyContext;
        BiPredicate<Map<String, Object>, Map<String, Object>> valueEqualsJudge = conflictKeyContext.getValueEqualsJudge();
        Objects.requireNonNull(valueEqualsJudge, "equals比较器为空");
        if (!valueEqualsJudge.test(oldValue, newValue)) {
            ConflictKeyException.of("参照列冲突！旧数据列:" + JSONUtil.toJsonStr(oldValue) + "新数据列:" + JSONUtil.toJsonStr(newValue))
                    .throwException();
        } else {
            collectDuplicateData(conflictKeyContext, key, oldValue, newValue);
        }
    }

    private void collectDuplicateData(ConflictKeyContext conflictKeyContext, String key, Map<String, Object> oldValue, Map<String, Object> newValue) {
        /**
         * 如果之前没有这个key的重复数据（即目前的newValue是第二个这个key的数据）将new value和old value 都加入
         * 否则（第三个以及之后）只加入new value
         */
        conflictKeyContext.getConflictKeyItems().computeIfPresent(key, (k, maps) -> {
            maps.add(newValue);
            return maps;
        });
        conflictKeyContext.getConflictKeyItems().putIfAbsent(key, ListUtil.list(false, oldValue, newValue));
    }


    @Override
    public List<Map<String, Object>> getLogDataList() {
        return conflictKeyContext.getConflictKeyItems().values().stream()
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
    }
}


